@objectstack/runtime 7.7.0 → 7.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +200 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +200 -17
- package/dist/index.js.map +1 -1
- package/package.json +18 -18
package/dist/index.cjs
CHANGED
|
@@ -324,6 +324,24 @@ var init_seed_loader = __esm({
|
|
|
324
324
|
for (const ref of objectRefs) {
|
|
325
325
|
const fieldValue = record[ref.field];
|
|
326
326
|
if (fieldValue === void 0 || fieldValue === null) continue;
|
|
327
|
+
if (typeof fieldValue === "object") {
|
|
328
|
+
const wrapped = fieldValue.externalId;
|
|
329
|
+
const hint = wrapped !== void 0 ? ` Pass the natural key directly: ${ref.field}: ${JSON.stringify(wrapped)}.` : ` Pass the target's ${ref.targetField} value as a plain string.`;
|
|
330
|
+
const error = {
|
|
331
|
+
sourceObject: objectName,
|
|
332
|
+
field: ref.field,
|
|
333
|
+
targetObject: ref.targetObject,
|
|
334
|
+
targetField: ref.targetField,
|
|
335
|
+
attemptedValue: fieldValue,
|
|
336
|
+
recordIndex: i,
|
|
337
|
+
message: `Invalid reference for ${objectName}.${ref.field}: expected a ${ref.targetObject}.${ref.targetField} natural-key string but got an object.${hint}`
|
|
338
|
+
};
|
|
339
|
+
errors.push(error);
|
|
340
|
+
allErrors.push(error);
|
|
341
|
+
this.logger.warn(`[SeedLoader] ${error.message}`, { recordIndex: i });
|
|
342
|
+
record[ref.field] = null;
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
327
345
|
if (typeof fieldValue !== "string" || this.looksLikeInternalId(fieldValue)) continue;
|
|
328
346
|
const targetMap = insertedRecords.get(ref.targetObject);
|
|
329
347
|
const resolvedId = targetMap?.get(String(fieldValue));
|
|
@@ -3589,7 +3607,8 @@ var _HttpDispatcher = class _HttpDispatcher {
|
|
|
3589
3607
|
if (protocol && typeof protocol.getMetaItem === "function") {
|
|
3590
3608
|
try {
|
|
3591
3609
|
const organizationId = await this.resolveActiveOrganizationId(_context);
|
|
3592
|
-
const
|
|
3610
|
+
const previewDrafts = query?.preview === "draft";
|
|
3611
|
+
const data = await protocol.getMetaItem({ type: singularType, name, packageId, organizationId, previewDrafts });
|
|
3593
3612
|
return { handled: true, response: this.success(data) };
|
|
3594
3613
|
} catch (e) {
|
|
3595
3614
|
}
|
|
@@ -3607,6 +3626,23 @@ var _HttpDispatcher = class _HttpDispatcher {
|
|
|
3607
3626
|
return { handled: true, response: this.error(e.message, 404) };
|
|
3608
3627
|
}
|
|
3609
3628
|
}
|
|
3629
|
+
if (parts.length === 1 && parts[0] === "_drafts" && (!method || method.toUpperCase() === "GET")) {
|
|
3630
|
+
const protocol = await this.resolveService("protocol");
|
|
3631
|
+
if (protocol && typeof protocol.listDrafts === "function") {
|
|
3632
|
+
try {
|
|
3633
|
+
const organizationId = await this.resolveActiveOrganizationId(_context);
|
|
3634
|
+
const data = await protocol.listDrafts({
|
|
3635
|
+
packageId: query?.packageId || void 0,
|
|
3636
|
+
type: query?.type || void 0,
|
|
3637
|
+
organizationId
|
|
3638
|
+
});
|
|
3639
|
+
return { handled: true, response: this.success(data) };
|
|
3640
|
+
} catch (e) {
|
|
3641
|
+
return { handled: true, response: this.error(e.message, 500) };
|
|
3642
|
+
}
|
|
3643
|
+
}
|
|
3644
|
+
return { handled: true, response: this.error("Draft listing not supported", 501) };
|
|
3645
|
+
}
|
|
3610
3646
|
if (parts.length === 1) {
|
|
3611
3647
|
const typeOrName = parts[0];
|
|
3612
3648
|
const packageId = query?.package || void 0;
|
|
@@ -3614,7 +3650,8 @@ var _HttpDispatcher = class _HttpDispatcher {
|
|
|
3614
3650
|
if (protocol && typeof protocol.getMetaItems === "function") {
|
|
3615
3651
|
try {
|
|
3616
3652
|
const organizationId = await this.resolveActiveOrganizationId(_context);
|
|
3617
|
-
const
|
|
3653
|
+
const previewDrafts = query?.preview === "draft";
|
|
3654
|
+
const data = await protocol.getMetaItems({ type: typeOrName, packageId, organizationId, previewDrafts });
|
|
3618
3655
|
if (data && (data.items !== void 0 || Array.isArray(data))) {
|
|
3619
3656
|
return { handled: true, response: this.success(data) };
|
|
3620
3657
|
}
|
|
@@ -3906,7 +3943,15 @@ var _HttpDispatcher = class _HttpDispatcher {
|
|
|
3906
3943
|
return { handled: true, response: this.success({ packages, total: packages.length }) };
|
|
3907
3944
|
}
|
|
3908
3945
|
if (parts.length === 0 && m === "POST") {
|
|
3909
|
-
const
|
|
3946
|
+
const manifest = body.manifest || body;
|
|
3947
|
+
let pkg;
|
|
3948
|
+
const protocolSvc = await this.resolveService("protocol").catch(() => null);
|
|
3949
|
+
if (protocolSvc && typeof protocolSvc.installPackage === "function") {
|
|
3950
|
+
const out = await protocolSvc.installPackage({ manifest, settings: body.settings });
|
|
3951
|
+
pkg = out?.package ?? out;
|
|
3952
|
+
} else {
|
|
3953
|
+
pkg = registry.installPackage(manifest, body.settings);
|
|
3954
|
+
}
|
|
3910
3955
|
const res = this.success(pkg);
|
|
3911
3956
|
res.status = 201;
|
|
3912
3957
|
return { handled: true, response: res };
|
|
@@ -3942,6 +3987,42 @@ var _HttpDispatcher = class _HttpDispatcher {
|
|
|
3942
3987
|
}
|
|
3943
3988
|
return { handled: true, response: this.error("Metadata service not available", 503) };
|
|
3944
3989
|
}
|
|
3990
|
+
if (parts.length === 2 && parts[1] === "publish-drafts" && m === "POST") {
|
|
3991
|
+
const id = decodeURIComponent(parts[0]);
|
|
3992
|
+
const protocol = await this.resolveService("protocol");
|
|
3993
|
+
if (protocol && typeof protocol.publishPackageDrafts === "function") {
|
|
3994
|
+
try {
|
|
3995
|
+
const organizationId = await this.resolveActiveOrganizationId(_context);
|
|
3996
|
+
const result = await protocol.publishPackageDrafts({
|
|
3997
|
+
packageId: id,
|
|
3998
|
+
...organizationId ? { organizationId } : {},
|
|
3999
|
+
...body?.actor ? { actor: body.actor } : {}
|
|
4000
|
+
});
|
|
4001
|
+
return { handled: true, response: this.success(result) };
|
|
4002
|
+
} catch (e) {
|
|
4003
|
+
return { handled: true, response: this.error(e.message, e.statusCode || 500) };
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
return { handled: true, response: this.error("Draft publishing not supported", 501) };
|
|
4007
|
+
}
|
|
4008
|
+
if (parts.length === 2 && parts[1] === "discard-drafts" && m === "POST") {
|
|
4009
|
+
const id = decodeURIComponent(parts[0]);
|
|
4010
|
+
const protocol = await this.resolveService("protocol");
|
|
4011
|
+
if (protocol && typeof protocol.discardPackageDrafts === "function") {
|
|
4012
|
+
try {
|
|
4013
|
+
const organizationId = await this.resolveActiveOrganizationId(_context);
|
|
4014
|
+
const result = await protocol.discardPackageDrafts({
|
|
4015
|
+
packageId: id,
|
|
4016
|
+
...organizationId ? { organizationId } : {},
|
|
4017
|
+
...body?.actor ? { actor: body.actor } : {}
|
|
4018
|
+
});
|
|
4019
|
+
return { handled: true, response: this.success(result) };
|
|
4020
|
+
} catch (e) {
|
|
4021
|
+
return { handled: true, response: this.error(e.message, e.statusCode || 500) };
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
return { handled: true, response: this.error("Draft discarding not supported", 501) };
|
|
4025
|
+
}
|
|
3945
4026
|
if (parts.length === 2 && parts[1] === "revert" && m === "POST") {
|
|
3946
4027
|
const id = decodeURIComponent(parts[0]);
|
|
3947
4028
|
const metadataService = await this.getService(import_system2.CoreServiceName.enum.metadata);
|
|
@@ -3967,9 +4048,27 @@ var _HttpDispatcher = class _HttpDispatcher {
|
|
|
3967
4048
|
}
|
|
3968
4049
|
if (parts.length === 1 && m === "DELETE") {
|
|
3969
4050
|
const id = decodeURIComponent(parts[0]);
|
|
3970
|
-
const
|
|
3971
|
-
|
|
3972
|
-
|
|
4051
|
+
const registryRemoved = registry.uninstallPackage(id);
|
|
4052
|
+
let persisted = void 0;
|
|
4053
|
+
const protocol = await this.resolveService("protocol");
|
|
4054
|
+
if (protocol && typeof protocol.deletePackage === "function") {
|
|
4055
|
+
try {
|
|
4056
|
+
const organizationId = await this.resolveActiveOrganizationId(_context);
|
|
4057
|
+
const keepData = query?.keepData === "true" || query?.keepData === "1";
|
|
4058
|
+
persisted = await protocol.deletePackage({
|
|
4059
|
+
packageId: id,
|
|
4060
|
+
...organizationId ? { organizationId } : {},
|
|
4061
|
+
...keepData ? { keepData: true } : {}
|
|
4062
|
+
});
|
|
4063
|
+
} catch (e) {
|
|
4064
|
+
return { handled: true, response: this.error(e.message, e.statusCode || 500) };
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
const deletedCount = persisted?.deletedCount ?? 0;
|
|
4068
|
+
if (!registryRemoved && deletedCount === 0) {
|
|
4069
|
+
return { handled: true, response: this.error(`Package '${id}' not found`, 404) };
|
|
4070
|
+
}
|
|
4071
|
+
return { handled: true, response: this.success({ success: true, registryRemoved, persisted }) };
|
|
3973
4072
|
}
|
|
3974
4073
|
} catch (e) {
|
|
3975
4074
|
return { handled: true, response: this.error(e.message, e.statusCode || 500) };
|
|
@@ -5441,6 +5540,14 @@ function createDispatcherPlugin(config = {}) {
|
|
|
5441
5540
|
errorResponse(err, res);
|
|
5442
5541
|
}
|
|
5443
5542
|
});
|
|
5543
|
+
server.post(`${prefix}/packages/:id/publish-drafts`, async (req, res) => {
|
|
5544
|
+
try {
|
|
5545
|
+
const result = await dispatcher.handlePackages(`/${req.params.id}/publish-drafts`, "POST", req.body, {}, { request: req });
|
|
5546
|
+
sendResult(result, res);
|
|
5547
|
+
} catch (err) {
|
|
5548
|
+
errorResponse(err, res);
|
|
5549
|
+
}
|
|
5550
|
+
});
|
|
5444
5551
|
server.post(`${prefix}/packages/:id/revert`, async (req, res) => {
|
|
5445
5552
|
try {
|
|
5446
5553
|
const result = await dispatcher.handlePackages(`/${req.params.id}/revert`, "POST", req.body, {}, { request: req });
|
|
@@ -6542,6 +6649,16 @@ var CAPABILITY_PROVIDERS = {
|
|
|
6542
6649
|
pkg: "@objectstack/service-ai",
|
|
6543
6650
|
export: "AIServicePlugin"
|
|
6544
6651
|
},
|
|
6652
|
+
// AI Studio — AI-driven metadata authoring ("online development"). This is
|
|
6653
|
+
// a commercial capability that ships in the private @objectstack/service-ai-studio
|
|
6654
|
+
// package (not part of the open-source framework). The dynamic import below
|
|
6655
|
+
// silently skips when the package isn't installed, so the open-source build
|
|
6656
|
+
// is unaffected; cloud and enterprise installs that ship the package light it
|
|
6657
|
+
// up. Pair with `ai` in `requires` (it attaches via the `ai:ready` hook).
|
|
6658
|
+
aiStudio: {
|
|
6659
|
+
pkg: "@objectstack/service-ai-studio",
|
|
6660
|
+
export: "AIStudioPlugin"
|
|
6661
|
+
},
|
|
6545
6662
|
analytics: {
|
|
6546
6663
|
pkg: "@objectstack/service-analytics",
|
|
6547
6664
|
export: "AnalyticsServicePlugin",
|
|
@@ -6868,6 +6985,7 @@ var ArtifactKernelFactory = class {
|
|
|
6868
6985
|
this.envRegistry = config.envRegistry;
|
|
6869
6986
|
this.logger = config.logger ?? console;
|
|
6870
6987
|
this.kernelConfig = config.kernelConfig;
|
|
6988
|
+
this.defaultRequires = config.defaultRequires ?? [];
|
|
6871
6989
|
this.authBaseSecret = (config.authBaseSecret ?? (0, import_types3.readEnvWithDeprecation)("OS_AUTH_SECRET", ["AUTH_SECRET", "BETTER_AUTH_SECRET"]) ?? "").trim();
|
|
6872
6990
|
}
|
|
6873
6991
|
async create(environmentId) {
|
|
@@ -7034,7 +7152,10 @@ var ArtifactKernelFactory = class {
|
|
|
7034
7152
|
});
|
|
7035
7153
|
}
|
|
7036
7154
|
const requiresRaw = (Array.isArray(bundle?.requires) ? bundle.requires : null) ?? (Array.isArray(sys?.requires) ? sys.requires : null) ?? [];
|
|
7037
|
-
const requires =
|
|
7155
|
+
const requires = [
|
|
7156
|
+
...requiresRaw,
|
|
7157
|
+
...this.defaultRequires
|
|
7158
|
+
].filter((x) => typeof x === "string" && x.length > 0);
|
|
7038
7159
|
if (requires.length > 0) {
|
|
7039
7160
|
const installed = await loadCapabilities({
|
|
7040
7161
|
kernel,
|
|
@@ -7453,6 +7574,61 @@ var AuthProxyPlugin = class {
|
|
|
7453
7574
|
return c.text(`sso-exchange failed: ${err?.message ?? String(err)}`, 500);
|
|
7454
7575
|
}
|
|
7455
7576
|
}
|
|
7577
|
+
if (c.req.method === "POST" && subPath === "set-initial-password") {
|
|
7578
|
+
try {
|
|
7579
|
+
let body = {};
|
|
7580
|
+
try {
|
|
7581
|
+
body = await c.req.json();
|
|
7582
|
+
} catch {
|
|
7583
|
+
body = {};
|
|
7584
|
+
}
|
|
7585
|
+
const newPassword = body?.newPassword;
|
|
7586
|
+
if (typeof newPassword !== "string" || newPassword.length === 0) {
|
|
7587
|
+
return c.json({ success: false, error: { code: "invalid_request", message: "newPassword is required" } }, 400);
|
|
7588
|
+
}
|
|
7589
|
+
if (typeof authSvc?.getAuthContext !== "function") {
|
|
7590
|
+
return c.json({ success: false, error: { code: "unavailable", message: "Auth context unavailable" } }, 503);
|
|
7591
|
+
}
|
|
7592
|
+
let userId;
|
|
7593
|
+
try {
|
|
7594
|
+
const api = typeof authSvc.getApi === "function" ? await authSvc.getApi() : null;
|
|
7595
|
+
const session = await api?.getSession?.({ headers: c.req.raw.headers });
|
|
7596
|
+
userId = session?.user?.id ? String(session.user.id) : void 0;
|
|
7597
|
+
} catch {
|
|
7598
|
+
}
|
|
7599
|
+
if (!userId) {
|
|
7600
|
+
return c.json({ success: false, error: { code: "unauthorized", message: "Sign in first" } }, 401);
|
|
7601
|
+
}
|
|
7602
|
+
const setPwCtx = await authSvc.getAuthContext();
|
|
7603
|
+
if (!setPwCtx?.internalAdapter || !setPwCtx?.password) {
|
|
7604
|
+
return c.json({ success: false, error: { code: "unavailable", message: "Auth context unavailable" } }, 503);
|
|
7605
|
+
}
|
|
7606
|
+
const minLen = setPwCtx.password?.config?.minPasswordLength ?? 8;
|
|
7607
|
+
const maxLen = setPwCtx.password?.config?.maxPasswordLength ?? 128;
|
|
7608
|
+
if (newPassword.length < minLen) {
|
|
7609
|
+
return c.json({ success: false, error: { code: "password_too_short", message: `Password must be at least ${minLen} characters` } }, 400);
|
|
7610
|
+
}
|
|
7611
|
+
if (newPassword.length > maxLen) {
|
|
7612
|
+
return c.json({ success: false, error: { code: "password_too_long", message: `Password must be at most ${maxLen} characters` } }, 400);
|
|
7613
|
+
}
|
|
7614
|
+
const accounts = await setPwCtx.internalAdapter.findAccounts(userId);
|
|
7615
|
+
const existingCredential = accounts?.find?.((a) => a.providerId === "credential" && a.password);
|
|
7616
|
+
if (existingCredential) {
|
|
7617
|
+
return c.json({ success: false, error: { code: "credential_account_exists", message: "A local password is already set for this account. Use change-password instead." } }, 409);
|
|
7618
|
+
}
|
|
7619
|
+
const passwordHash = await setPwCtx.password.hash(newPassword);
|
|
7620
|
+
await setPwCtx.internalAdapter.createAccount({
|
|
7621
|
+
userId,
|
|
7622
|
+
providerId: "credential",
|
|
7623
|
+
accountId: userId,
|
|
7624
|
+
password: passwordHash
|
|
7625
|
+
});
|
|
7626
|
+
return c.json({ success: true });
|
|
7627
|
+
} catch (err) {
|
|
7628
|
+
ctx.logger?.error?.("[AuthProxyPlugin] set-initial-password failed", err instanceof Error ? err : new Error(String(err)));
|
|
7629
|
+
return c.json({ success: false, error: { code: "set_password_failed", message: String(err?.message ?? err) } }, 500);
|
|
7630
|
+
}
|
|
7631
|
+
}
|
|
7456
7632
|
const fn = await resolveAuthHandler(authSvc);
|
|
7457
7633
|
if (!fn) {
|
|
7458
7634
|
return c.json({ error: "auth_service_unavailable", environmentId }, 503);
|
|
@@ -7638,13 +7814,7 @@ var MarketplaceProxyPlugin = class _MarketplaceProxyPlugin {
|
|
|
7638
7814
|
}
|
|
7639
7815
|
const target = `${cloudUrl}${incomingUrl.pathname}${incomingUrl.search}`;
|
|
7640
7816
|
if (method !== "GET" && method !== "HEAD") {
|
|
7641
|
-
return
|
|
7642
|
-
success: false,
|
|
7643
|
-
error: {
|
|
7644
|
-
code: "marketplace_method_not_allowed",
|
|
7645
|
-
message: `Marketplace proxy only forwards GET/HEAD; install via cloud.`
|
|
7646
|
-
}
|
|
7647
|
-
}, 405);
|
|
7817
|
+
return next();
|
|
7648
7818
|
}
|
|
7649
7819
|
const accept = c.req.header("accept") ?? "application/json";
|
|
7650
7820
|
const acceptLang = c.req.header("accept-language") ?? "";
|
|
@@ -7868,7 +8038,8 @@ var RuntimeConfigPlugin = class {
|
|
|
7868
8038
|
const rawApp = httpServer.getRawApp();
|
|
7869
8039
|
const features = {
|
|
7870
8040
|
installLocal: this.installLocal,
|
|
7871
|
-
marketplace: true
|
|
8041
|
+
marketplace: true,
|
|
8042
|
+
aiStudio: this.aiStudio
|
|
7872
8043
|
};
|
|
7873
8044
|
let envRegistry = null;
|
|
7874
8045
|
try {
|
|
@@ -7919,6 +8090,7 @@ var RuntimeConfigPlugin = class {
|
|
|
7919
8090
|
};
|
|
7920
8091
|
this.cloudUrl = config.controlPlaneUrl === "" ? "" : resolveCloudUrl(config.controlPlaneUrl) ?? "";
|
|
7921
8092
|
this.installLocal = !!config.installLocal;
|
|
8093
|
+
this.aiStudio = config.aiStudio !== false;
|
|
7922
8094
|
this.singleEnvironment = !!config.singleEnvironment;
|
|
7923
8095
|
const envName = (typeof process !== "undefined" ? process.env?.OS_PRODUCT_NAME : void 0)?.trim();
|
|
7924
8096
|
const envShort = (typeof process !== "undefined" ? process.env?.OS_PRODUCT_SHORT_NAME : void 0)?.trim();
|
|
@@ -8110,7 +8282,8 @@ var ObjectOSEnvironmentPlugin = class {
|
|
|
8110
8282
|
const factory = new ArtifactKernelFactory({
|
|
8111
8283
|
client,
|
|
8112
8284
|
envRegistry,
|
|
8113
|
-
logger: ctx.logger
|
|
8285
|
+
logger: ctx.logger,
|
|
8286
|
+
defaultRequires: this.config.defaultRequires
|
|
8114
8287
|
});
|
|
8115
8288
|
const kernelManager = new KernelManager({
|
|
8116
8289
|
factory,
|
|
@@ -8167,7 +8340,17 @@ async function createObjectOSStack(config) {
|
|
|
8167
8340
|
};
|
|
8168
8341
|
const enginePlugins = await createHostEnginePlugins();
|
|
8169
8342
|
return {
|
|
8170
|
-
plugins: [
|
|
8343
|
+
plugins: [
|
|
8344
|
+
...enginePlugins,
|
|
8345
|
+
new ObjectOSEnvironmentPlugin(merged),
|
|
8346
|
+
new AuthProxyPlugin(),
|
|
8347
|
+
new MarketplaceProxyPlugin({ controlPlaneUrl: merged.controlPlaneUrl === "file" ? void 0 : merged.controlPlaneUrl }),
|
|
8348
|
+
new RuntimeConfigPlugin({ controlPlaneUrl: merged.controlPlaneUrl === "file" ? void 0 : merged.controlPlaneUrl, installLocal: false }),
|
|
8349
|
+
// Host-supplied product/policy plugins (the official seam — see
|
|
8350
|
+
// ObjectOSStackConfig.extraPlugins). Appended last so they mount
|
|
8351
|
+
// after the framework defaults.
|
|
8352
|
+
...config.extraPlugins ?? []
|
|
8353
|
+
],
|
|
8171
8354
|
api: {
|
|
8172
8355
|
enableProjectScoping: true,
|
|
8173
8356
|
projectResolution: "auto",
|